﻿/**
 * http://www.cnblogs.com/anjou/archive/2008/05/25/1206832.html
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Collections.Specialized;
using System.IO;

namespace RedFoxUtils
{
  /// <summary>
  /// 支持 Session 和 Cookie 的 WebClient。
  /// </summary>
  public class HttpClient : WebClient, IHttpClient
  {
    // Cookie 容器
    private CookieContainer cookieContainer;

    /// <summary>
    /// 創建一個新的 WebClient 實例。
    /// </summary>
    public HttpClient()
    {
      this.cookieContainer = new CookieContainer();
    }

    /// <summary>
    /// 創建一個新的 WebClient 實例。
    /// </summary>
    /// <param name="cookie">Cookie 容器</param>
    public HttpClient(CookieContainer cookies)
    {
      this.cookieContainer = cookies;
    }

    /// <summary>
    /// Cookie 容器
    /// </summary>
    public CookieContainer Cookies
    {
      get { return this.cookieContainer; }
      set { this.cookieContainer = value; }
    }

    /// <summary>
    /// 返回帶有 Cookie 的 HttpWebRequest。
    /// </summary>
    /// <param name="address"></param>
    /// <returns></returns>
    protected override WebRequest GetWebRequest(Uri address)
    {
      WebRequest request = base.GetWebRequest(address);
      if (request is HttpWebRequest)
      {
        HttpWebRequest httpRequest = request as HttpWebRequest;
        httpRequest.CookieContainer = cookieContainer;
        httpRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2;)";
        httpRequest.KeepAlive = false;
      }
      return request;
    }

    #region 封裝了PostData, GetSrc 和 GetFile 方法
    /// <summary>
    /// 向指定的 URL POST 數據，並返回頁面
    /// </summary>
    /// <param name="uriString">POST URL</param>
    /// <param name="postString">POST 的 數據</param>
    /// <param name="postStringEncoding">POST 數據的 CharSet</param>
    /// <param name="dataEncoding">頁面的 CharSet</param>
    /// <returns>頁面的源文件</returns>
    public string PostData(string uriString, string postString, string postStringEncoding, string dataEncoding, out string msg)
    {
      try
      {
        // 將 Post 字符串轉換成字節數組
        byte[] postData = Encoding.GetEncoding(postStringEncoding).GetBytes(postString);
        this.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
        // 上傳數據，返回頁面的字節數組
        byte[] responseData = this.UploadData(uriString, "POST", postData);
        // 將返回的將字節數組轉換成字符串(HTML);
        string srcString = Encoding.GetEncoding(dataEncoding).GetString(responseData);
        srcString = srcString.Replace("\t", "");
        srcString = srcString.Replace("\r", "");
        srcString = srcString.Replace("\n", "");
        msg = string.Empty;
        return srcString;
      }
      catch (WebException we)
      {
        msg = we.Message;
        return string.Empty;
      }
    }

    /// <summary>
    /// 獲得指定 URL 的源文件
    /// </summary>
    /// <param name="uriString">頁面 URL</param>
    /// <param name="dataEncoding">頁面的 CharSet</param>
    /// <returns>頁面的源文件</returns>
    public string GetSrc(string uriString, string dataEncoding, out string msg)
    {
      if (String.IsNullOrEmpty(uriString))
      {
        msg = "";
        return "";
      }

      try
      {
        // 返回頁面的字節數組
        byte[] responseData = this.DownloadData(uriString);
        // 將返回的將字節數組轉換成字符串(HTML);
        string srcString = Encoding.GetEncoding(dataEncoding).GetString(responseData);
        srcString = srcString.Replace("\t", "");
        srcString = srcString.Replace("\r", "");
        srcString = srcString.Replace("\n", "");
        msg = string.Empty;
        return srcString;
      }
      catch (WebException we)
      {
        msg = we.Message;
        return string.Empty;
      }
    }

    /// <summary>
    /// 從指定的 URL 下載文件到本地
    /// </summary>
    /// <param name="uriString">文件 URL</param>
    /// <param name="fileName">本地文件的完成路徑</param>
    /// <returns></returns>
    public bool GetFile(string urlString, string fileName, out string msg)
    {
      try
      {
        this.DownloadFile(urlString, fileName);
        msg = string.Empty;
        return true;
      }
      catch (WebException we)
      {
        msg = we.Message;
        return false;
      }
    }
    #endregion

    #region 新的上傳方法
    public string UploadFile2(string url, string file, NameValueCollection nvc)
    {
      long length = 0;
      string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");

      HttpWebRequest httpWebRequest2 = (HttpWebRequest)GetWebRequest(new Uri(url));
      httpWebRequest2.ContentType = "multipart/form-data; boundary=" + boundary;
      httpWebRequest2.Method = "POST";
      httpWebRequest2.KeepAlive = true;
      httpWebRequest2.Credentials = System.Net.CredentialCache.DefaultCredentials;
      //httpWebRequest2.Headers["Content-Disposition"] = String.Format( "attachment; name=\"{0}\" filename=\"{1}\"\r\n Content-length: {2}\r\n Content-Type: application/octet-stream\r\n\r\n", "file", File.ReadAllBytes(file).Length, Path.GetFileName(file));

      Stream memStream = new System.IO.MemoryStream();
      byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");
      string formdataTemplate = "\r\n--" + boundary + "\r\nContent-Disposition: form-data; name=\"{0}\";\r\n\r\n{1}";

      foreach (string key in nvc.Keys)
      {
        string formitem = string.Format(formdataTemplate, key, nvc[key]);
        byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem);
        memStream.Write(formitembytes, 0, formitembytes.Length);
      }
      memStream.Write(boundarybytes, 0, boundarybytes.Length);

      string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\n Content-Type: application/octet-stream\r\n\r\n";

      string header = string.Format(headerTemplate, "file", Path.GetFileName(file));
      byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header);
      memStream.Write(headerbytes, 0, headerbytes.Length);

      FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
      byte[] buffer = new byte[1024];

      int bytesRead = 0;
      while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0)
      {
        memStream.Write(buffer, 0, bytesRead);
      }
      memStream.Write(boundarybytes, 0, boundarybytes.Length);
      fileStream.Close();

      httpWebRequest2.ContentLength = memStream.Length;

      Stream requestStream = httpWebRequest2.GetRequestStream();
      memStream.Position = 0;
      byte[] tempBuffer = new byte[memStream.Length];
      memStream.Read(tempBuffer, 0, tempBuffer.Length);
      memStream.Close();
      requestStream.Write(tempBuffer, 0, tempBuffer.Length);
      //requestStream.Close();

      WebResponse webResponse2 = httpWebRequest2.GetResponse();
      Stream stream2 = webResponse2.GetResponseStream();
      StreamReader reader2 = new StreamReader(stream2);
      string result = reader2.ReadToEnd();

      webResponse2.Close();
      httpWebRequest2 = null;
      webResponse2 = null;
      return result;
    }
    #endregion
  }
}
